#pragma once
#include "../mqcommon/helper.hpp"
#include "../mqcommon/logger.hpp"
#include "../mqcommon/msg.pb.h"
#include <functional>
#include <mutex>
// #include <unordered_map> 我没有写他，它不会报错
using ConsumerCallback = std::function<void(const std::string& tag, const BasicProperty* bp, const std::string& body)>;
struct Consumer
{
    using Ptr = std::shared_ptr<Consumer>;

    std::string tag;
    std::string queueName;
    bool autoAck;
    ConsumerCallback callback;
    Consumer(const std::string& tagValue, const std::string& queueNameValue, bool autoAckValue, const ConsumerCallback& cb)
        :tag(tagValue)
        ,queueName(queueNameValue)
        ,autoAck(autoAckValue)
        ,callback(cb)
    {}
};

class QueueConsumer             //一个队列管理的所有的consumer
{
public:
    using Ptr = std::shared_ptr<QueueConsumer>;
    QueueConsumer(const std::string& queueName)
        :_queueName(queueName), _rrSeq(0)
    {}

    Consumer::Ptr create(const std::string& tagValue, const std::string& queueNameValue, bool autoAckValue, const ConsumerCallback& cb)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        for(auto& consumer : _consumers)            //判断该队列是否已经存在这个消费者
            if(consumer->tag == tagValue) 
            {
                DLOG("消费者:%s, 已存在", consumer->tag.c_str());
                // return Consumer::Ptr();  //这里逻辑不大对，存在就返回这个才对
                return consumer;
            }
        
        Consumer::Ptr newComsumer = std::make_shared<Consumer>(tagValue, queueNameValue, autoAckValue, cb);         //要么是没有加进去
        _consumers.push_back(newComsumer);          //加入内存中管理
        DLOG("消费者地址：%p", newComsumer.get());
        DLOG("_consumers个数：%ld", _consumers.size());
        return newComsumer;
    }
    void remove(const std::string& tagValue)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _consumers.begin();
        for(auto it = _consumers.begin(); it != _consumers.end(); ++it)     
        {
            if((*it)->tag == tagValue)
            {
                _consumers.erase(it);
                return;
            }
        }
        DLOG("队列中没有这个消费者:%s", (*it)->tag.c_str());
    }
    Consumer::Ptr choose()                 //怎么进去两次？                                         //
    {
        std::unique_lock<std::mutex> lock(_mutex);
        DLOG("choose里的消费者个数：%ld", _consumers.size());
        if(_consumers.empty()) return Consumer::Ptr();
        uint64_t index = _rrSeq % _consumers.size();
        DLOG("消费者地址：%p", _consumers[index].get());
        DLOG("index：%ld", index);

        _rrSeq++;
        return _consumers[index];
    }
    bool empty() //消费者是否为空
    {
        return _consumers.empty();
    }
    bool exists(const std::string& tagValue) //有无消费者
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _consumers.begin();
        for(auto it = _consumers.begin(); it != _consumers.end(); ++it)     
            if((*it)->tag == tagValue)
                return true;
        return false;
    }
    void clear()
    {
        _consumers.clear();
    }
private:
    std::mutex _mutex;
    std::string _queueName;
    uint64_t _rrSeq;
    std::vector<Consumer::Ptr> _consumers;
};

class QueueConsumerManager       //管理所有队列的所有消费者
{
public:
    using Ptr = std::shared_ptr<QueueConsumerManager>;
    QueueConsumerManager() {}
    void initQueueConsumer(const std::string& queue)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _queueConsumers.find(queue);
        if(it != _queueConsumers.end())
        {
            DLOG("队列%s, 的QueueConsumer已存在", queue.c_str());
            return;
        }
        QueueConsumer::Ptr ptr = std::make_shared<QueueConsumer>(queue);
        _queueConsumers.insert({queue, ptr});
    }
    void destoryQueueConsumer(const std::string& queue)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _queueConsumers.erase(queue);
    }
    
    Consumer::Ptr create(const std::string& tagValue, const std::string& queue, bool autoAckValue, const ConsumerCallback& cb)
    {
        QueueConsumer::Ptr queueConsumerPtr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _queueConsumers.find(queue);
            if(it == _queueConsumers.end())
            {
                DLOG("队列%s, 不存在", queue.c_str());
                return Consumer::Ptr();
            }
            queueConsumerPtr = it->second;
        }
        return queueConsumerPtr->create(tagValue, queue, autoAckValue, cb);
    }
    void remove(const std::string& queue, const std::string& tagValue)
    {
        QueueConsumer::Ptr queueConsumerPtr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _queueConsumers.find(queue);
            if(it == _queueConsumers.end())
            {
                DLOG("队列%s, 不存在", queue.c_str());
                return ;
            }
            queueConsumerPtr = it->second;
        }
        queueConsumerPtr->remove(tagValue);
    }
    Consumer::Ptr choose(const std::string& queue)
    {
        QueueConsumer::Ptr queueConsumerPtr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _queueConsumers.find(queue);
            if(it == _queueConsumers.end())
            {
                DLOG("队列%s, 不存在", queue.c_str());
                return Consumer::Ptr();
            }
            queueConsumerPtr = it->second;
        }
        return queueConsumerPtr->choose();
    }
    bool empty(const std::string& queue)
    {
        QueueConsumer::Ptr queueConsumerPtr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _queueConsumers.find(queue);
            if(it == _queueConsumers.end())
            {
                DLOG("队列%s, 不存在", queue.c_str());
                return false;
            }
            queueConsumerPtr = it->second;
        }
        return queueConsumerPtr->empty();
    }
    bool exists(const std::string& queue, const std::string& tagValue)
    {
        QueueConsumer::Ptr queueConsumerPtr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _queueConsumers.find(queue);
            if(it == _queueConsumers.end())
            {
                DLOG("队列%s, 不存在", queue.c_str());
                return false;
            }
            queueConsumerPtr = it->second;
        }
        return queueConsumerPtr->exists(tagValue);
    }
    void clear()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _queueConsumers.clear();
    }
private:
    std::mutex _mutex;
    std::unordered_map<std::string, QueueConsumer::Ptr> _queueConsumers;        //锁这个对象
};